Chapter 02. 리팩터링 원칙
리팩터링의 정의
- 코드를 이해하고 수정하기 쉽게 만드는 것이 목적이다.
- 동작을 보존하는 작은 단계들을 거쳐 코드를 수정하고 이러한 단계들을 순차적으로 연결하여 변화를 만들어 내는 일.
- 리팩터링하는 동안에는 코드가 항상 정상 작동하기 때문에 언제든 멈출 수 있으며, 그렇지 않다면 리팩터링이 아니다.
두 개의 모자
- 기능을 추가할 때는 기존 코드를 건드리지 않고 새 기능을 추가하기만 한다.
- 리팩터링할 때는 기능 추가 없이 코드 재구성만을 한다.
- 무슨 모자를 쓰고 작업하고 있는지 분명하게 하자.
리팩터링하는 이유
- 설계가 좋아진다.
- 중복코드를 제거하면 예측 가능한 고유한 일을 수행하고 있음을 보장할 수 있게 된다.
- 이해해야 할 코드량이 줄게 된다.
- 이해하기 쉬워진다.
- 개발자에게 더 잘 읽히는 코드.
- 코드만 봐도 내용을 쉽게 알 수 있는 코드.
- 버그를 찾기 쉬워진다.
- 프로그래밍 속도가 높아진다.
- 모듈화와 명확한 설계, 좋은 품질의 베이스 코드는 새로운 기능을 추가하기 쉽게 만든다.
- 리팩터링을 통해 계속해서 설계를 개선하고, 좋은 상태를 유지하게 할 수 있다.
언제 리팩터링해야 할까
- 3의 법칙
- 일단 그냥 한다.
- 두 번째 비슷한 일을 할 때, 중복이 생기지만 일단 계속한다.
- 세 번째가 되면 리팩터링한다.
- 기능을 새로 추가하기 직전
- 필요한 코드가 비슷하게 존재한다면, 복사하지 말고 리팩터링하자.
- 코드를 파악(수정)할 때
- 이해된 변수에 적절한 이름 지어주기
- 긴 함수를 나누기
- 코드를 파악했다면, 이해한 내용을 코드에 반영하자.
- 쓰레기 줍기
- 작다면 즉시 고치고, 크다면 메모하고 이후에 처리하자.
- 수시로 기회 될 때마다 하자.
- 대규모 리팩터링은 작게 나눠서 조금씩 하자.
- 코드리뷰
- 이럴 때는 하지 말자
- 아직 세세하게 이해가 안 된, 자주 쓰는 코드
- 새로 작성하는 게 나아 보이는 코드
리팩터링 시 고려할 문제
- 리팩토링은 경제적인 이유로 한다.
- 코드 소유권은 개인보다는 팀 단위가 좋다.
- 브랜치는 자주 통합되어야 리팩터링에 좋다.
- 성공/실패 여부를 판단하는 테스트 코드 작성.
- 레거시 코드가 있다면 테스트 작성부터.
리팩터링, 아키텍처, 애그니
- 변화를 예상하고, 유연하게 대응하려다 보면 장황해진다.
- 그저 현재 파악한 요구사항만 멋지게 설계하고 해결하자.
- 진행하면서 요구사항을 알게 된다면 그에 맞게 리팩터링하자.
- 하지만 앞으로의 변경이 뻔히 보이고 그것이 리팩터링을 어렵게 만든다면, 그때 유연성 매커니즘을 추가한다.
- ↑ 애그니라 부른다. (you aren't going to need it)
- 선제적인 설계와 점진적 설계의 균형.
- 후자에 더 무게를 둔 진화형 아키텍처
- 설계에 관한 결정을 시간을 두고 반복해서 내린다.
리팩터링과 소프트웨어 개발 프로세스
- 익스트림 프로그래밍이란, 지속적 통합(CI), 자가 테스트 코드, 리팩터링 등의 기법들을 묶은 프로세스다.
- 자가 테스트 코드와 리팩터링을 묶어서 테스트 주도 개발(TDD)라 칭한다.
- 리팩터링의 첫 번째 토대는 자가 테스트 코드다.
- CI를 통해 팀원간의 코드가 계속 통합되어야 높은 효과가 있다.
- 자가 테스트 코드 + CI + 리팩터링 => 애그니 가능
- 자가 테스트 코드 + CI + 리팩터링 => 배포 주기를 짧게 가져갈 수 있도록 만들어준다.
리팩터링과 성능
- 리팩터링을 하면 성능을 좋게 만들기 쉬워진다.
- 추측만으로 성능에 대해 판단하지 마라.
- 대부분은 프로그램은 극히 일부 구간에서 많은 시간을 소비한다. 때문에 코드 전체를 최적화한다면 효과는 거의 없고 코드만 덜 명료해질 뿐이다.
- 의도적으로 성능 최적화에 돌입하기 전에는 성능에 신경쓰지 말고 코드를 다루기 쉽게 만드는데 집중해라.